/*
    mysql数据库相关 c API接口的说明：

// 0. Mysql操作句柄初始化
// 参数说明:
// mysql为空则动态申请句柄空间进⾏初始化
// 返回值: 成功返回句柄指针， 失败返回NULL
MYSQL *mysql_init(MYSQL *mysql);

// 1. 连接mysql服务器
// 参数说明:
// mysql--初始化完成的句柄
// host---连接的mysql服务器的地址
// user---连接的服务器的⽤⼾名
// passwd-连接的服务器的密码
// db ----默认选择的数据库名称
// port---连接的服务器的端⼝： 默认0是3306端⼝
// unix_socket---通信管道⽂件或者socket⽂件，通常置NULL
// client_flag---客⼾端标志位，通常置0
// 返回值：成功返回句柄指针，失败返回NULL
MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, 
    const char *passwd,const char *db, unsigned int port, 
    const char *unix_socket, unsigned long
    client_flag);

// 2. 设置当前客⼾端的字符集
// 参数说明:
// mysql--初始化完成的句柄
// csname--字符集名称，通常："utf8"
// 返回值：成功返回0， 失败返回⾮0
int mysql_set_character_set(MYSQL *mysql, const char *csname);

// 3. 选择操作的数据库
// 参数说明:
// mysql--初始化完成的句柄
// db-----要切换选择的数据库名称
// 返回值：成功返回0， 失败返回⾮0
int mysql_select_db(MYSQL *mysql, const char *db);

// 4. 执⾏sql语句
// 参数说明：
// mysql--初始化完成的句柄
// stmt_str--要执⾏的sql语句
// 返回值：成功返回0， 失败返回⾮0
int mysql_query(MYSQL *mysql, const char *stmt_str);

// 5. 保存查询结果到本地
// 参数说明:
// mysql--初始化完成的句柄
// 返回值：成功返回结果集的指针， 失败返回NULL
MYSQL_RES *mysql_store_result(MYSQL *mysql);

// 6. 获取结果集中的⾏数
// 参数说明:
// result--保存到本地的结果集地址
// 返回值：结果集中数据的条数
uint64_t mysql_num_rows(MYSQL_RES *result);

// 7. 获取结果集中的列数
// 参数说明:
// result--保存到本地的结果集地址
// 返回值：结果集中每⼀条数据的列数
unsigned int mysql_num_fields(MYSQL_RES *result);

// 8. 遍历结果集, 并且这个接⼝会保存当前读取结果位置，每次获取的都是下⼀条数据
// 参数说明:
// result--保存到本地的结果集地址
// 返回值：实际上是⼀个char **的指针，将每⼀条数据做成了字符串指针数组 
// row[0]-第0列 row[1]-第1列 ...
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

// 9. 释放结果集
// 参数说明:
// result--保存到本地的结果集地址
void mysql_free_result(MYSQL_RES *result);

// 10. 关闭数据库客⼾端连接，销毁句柄
// 参数说明：
// mysql--初始化完成的句柄
void mysql_close(MYSQL *mysql);

// 11. 获取mysql接⼝执⾏错误原因
// 参数说明：
// mysql--初始化完成的句柄
const char *mysql_error(MYSQL *mysql);

*/

#include <stdio.h>
#include <string.h>
#include <mysql/mysql.h>


#define HOST "127.0.0.1"    // 设置只能本地登录
#define PORT 3306           // 默认就是3306
#define USER "root"         // root 用户登录
#define PASS "ax020913"     // root 登录 mysql 的密码
#define DBNAME "gobang"     // 我们刚刚创建的 gobang 数据库

int main(){
    //1. 初始化mysql句柄
    // MYSQL *mysql_init(MYSQL *mysql);
    MYSQL *mysql = mysql_init(NULL);
    if (mysql == NULL) {
        printf("mysql init failed!\n");
        return -1;
    }
    
    //2. 连接服务器
    // MYSQL *mysql_real_connect(mysql, host, user, pass, dbname, port, unix_socket, flag);
    if (mysql_real_connect(mysql, HOST, USER, PASS, DBNAME, PORT, NULL, 0) == NULL) {
        printf("connect mysql server failed : %s\n", mysql_error(mysql));
        mysql_close(mysql);
        return -1;
    }
    
    //3. 设置客户端字符集(防止乱码)
    // int mysql_set_character_set(mysql, "utf8");
    if (mysql_set_character_set(mysql, "utf8") != 0) {
        printf("set client character failed : %s\n", mysql_error(mysql));
        mysql_close(mysql);
        return -1;
    }
    
    //4. 选择要操作的数据库
    // int mysql_select_db(mysql, dbname)
    // mysql_select_db(mysql, DBNAME);

    // 客户端对数据库中数据的操作:
    // 新增，修改，删除。都是只要sql语句执行成功了，数据库中的数据就发生了改变。
    // 没有反馈结果。查询是不一样的，因为需要首先执行语句成功，需要将查询结果保存到本地进行访问

    //5. 执行sql语句
    // int mysql_query(MYSQL *mysql,  char *sql);
    // 插入测试一下我们的数据库，插入一条信息试一试：
    // char *sql = "insert stu values(null, '小明', 18, 53, 68, 87);";
    // 更新上面的数据测试
    // char *sql = "update stu set ch=ch+40 where sn=1;";
    // 删除上面插入的数据测试
    // char *sql = "delete from stu where sn=1;";
    // 一般的写法是下面这样的：
    char *sql = "select * from stu;";
    int ret = mysql_query(mysql, sql);
    if (ret != 0) {
        printf("%s\n", sql);
        printf("mysql query failed : %s\n", mysql_error(mysql));
        mysql_close(mysql);
        return -1;
    }
    
    // 查询测试
    // 下面的6.7.8.9是根据查询语句来写的(没有的话也是可以不用写的):
    //6. 如果sql语句是查询语句，则需要保存结果到本地
    // MYSQL_RES *mysql_store_result(MYSQL *mysql)
    MYSQL_RES *res = mysql_store_result(mysql);
    if (res == NULL) {
        mysql_close(mysql);
        return -1;
    }
    //7. 获取结果集中的结果条数
    // int mysql_num_rows(MYSQL_RES *res);
    // int mysql_num_fields(MYSQL_RES *res);
    int num_row = mysql_num_rows(res);
    int num_col = mysql_num_fields(res);
    //8. 遍历保存到本地的结果集
    for (int i = 0; i < num_row; i++) {
        // MYSQL_ROW mysql_fetch_row(MYSQL *res);
        MYSQL_ROW row = mysql_fetch_row(res);
        for (int i = 0; i < num_col; i++) 
            printf("%s\t", row[i]);
        printf("\n");
    }
    //9. 释放结果集
    mysql_free_result(res);
    

    //10. 关闭连接，释放句柄
    mysql_close(mysql);
    
    return 0;
}

